package cn.com.gzheroli.auth.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.com.gzheroli.auth.pojo.TSDatacondition;
import cn.com.gzheroli.auth.pojo.TSDatarule;
import cn.com.gzheroli.auth.pojo.TSDataruleGroup;
import cn.com.gzheroli.auth.pojo.TSRoleDatarule;
import cn.com.gzheroli.auth.service.TSDataruleService;
import cn.com.gzheroli.bfw.pojo.base.TSDepart;
import cn.com.gzheroli.bfw.pojo.base.TSUser;
import cn.com.gzheroli.cache.SpringRedisCache;
import cn.com.gzheroli.core.common.model.json.AjaxJson;
import cn.com.gzheroli.core.common.service.CommonService;
import cn.com.gzheroli.util.GenSqlUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.io.Serializable;

import javax.annotation.Resource;

@Service("tSDataruleService")
public class TSDataruleServiceImpl  implements TSDataruleService {

	@Resource
	private CommonService commonService;
	@Autowired
    private SpringRedisCache cache;
 	/**
	 * 替换sql中的变量
	 * @param sql
	 * @return
	 */
 	public String replaceVal(String sql,TSDatarule t){
 		sql  = sql.replace("#{id}",String.valueOf(t.getId()));
 		sql  = sql.replace("#{rule_code}",String.valueOf(t.getRuleCode()));
 		sql  = sql.replace("#{rule_name}",String.valueOf(t.getRuleName()));
 		sql  = sql.replace("#{status}",String.valueOf(t.getStatus()));
 		sql  = sql.replace("#{UUID}",UUID.randomUUID().toString());
 		return sql;
 	}
 	/**
 	 * 
 	* <p>方法名: genSqlByModuleName<／p>
 	* <p>描述: 根据模块名称获取规则的sql<／p>
 	* @param moduleName 模块名称 
 	* @param alias 表别名
 	* @return
 	 */
 	public String genSqlByModuleName(String moduleName,String alias,TSUser user){
 		String sql="";
 		Map para=new HashMap();
 		para.put("userId", user.getId());
 		para.put("moduleName", moduleName);
 		String roleRuleSql="select distinct du.* from T_S_ROLE_DATARULE rd,T_S_DATARULE du where du.RULE_CODE=rd.RULE_CODE and du.status='1' and rd.STATUS='1' and du.MODULE_NAME=#{moduleName} and rd.ROLE_CODE in (select r.ROLE_CODE  from T_S_ROLE_USER ru,T_S_ROLE r where r.ID=ru.ROLE_ID and ru.USER_ID=#{userId})";
// 		List<TSRoleDatarule> roleRuleList=commonService.findByQueryString(roleRuleSql, TSRoleDatarule.class, para);
// 		String roleRuleStrs="";
// 		if(roleRuleList!=null&&!roleRuleList.isEmpty())
// 		for(TSRoleDatarule roleRuleStr:roleRuleList){
// 			roleRuleStrs=roleRuleStrs+","+roleRuleStr.getRuleCode();
// 		}
// 		if(roleRuleStrs.startsWith(","))
// 			roleRuleStrs=roleRuleStrs.substring(1);
// 		Map paraDataRule=new HashMap();
// 		paraDataRule.put("moduleName", moduleName);
 		//String ruleHql="select * from T_S_DATARULE ";
 		//ruleHql=ruleHql+" where status='1' and MODULE_Name=#{moduleName} and RULE_Code in ('"+roleRuleStrs.replaceAll(",", "','")+"') ";
 		List<TSDatarule> ruleList=commonService.findByQueryString(roleRuleSql, TSDatarule.class, para);
 		boolean firstRule=true;
 		if(ruleList!=null&&!ruleList.isEmpty())
 		for(TSDatarule rule:ruleList){
 			Map paraGroup=new HashMap();
 			paraGroup.put("ruleId", rule.getId());
 			String groupHql="select * from T_S_DATARULE_GROUP dg";
			groupHql=groupHql+" where dg.status='1' and dg.rule_Id=#{ruleId} and dg.P_GROUPID is null and exists (select 1 from T_S_DATACONDITION con where con.status='1' and con.group_Id=dg.id)";
	 		List<TSDataruleGroup> ruleGroupList=commonService.findByQueryString(groupHql, TSDataruleGroup.class, paraGroup);
	 		//if(ruleGroupList!=null&&!ruleGroupList.isEmpty())
	 		/*if(ruleList.size()>1)
	 		sql=sql+" or (";//多条规则取并集
*/	 		if(firstRule)
	 			sql=sql+" and (";
	 		else
	 			sql=sql+" or (";//多条规则取并集
	 		boolean firstGroupCondition=true;
			if (ruleGroupList != null && !ruleGroupList.isEmpty()) {
					for (TSDataruleGroup ruleGroup : ruleGroupList) {
						Map paraCondition = new HashMap();
						paraCondition.put("ruleId", rule.getId());
						paraCondition.put("groupId", ruleGroup.getId());
						String conditionSql = "";
						conditionSql = genConditionSql(ruleGroup.getId(), alias, user);
						String conditionHql = "select count(*)  from T_S_DATACONDITION ";
						conditionHql = conditionHql + " where status='1' and GROUP_ID=#{groupId}";
						Long conditionSize = commonService.getCountForJdbc(conditionHql, paraCondition);
						String subGroupHql = "select count(*) from T_S_DATARULE_GROUP ";
						subGroupHql = subGroupHql + " where status='1' and RULE_ID=#{ruleId} and P_GROUPID=#{groupId}";
						Long size = commonService.getCountForJdbc(subGroupHql, paraCondition);
						if (size > 0)
							conditionSql = conditionSql
									+ genGroupSql(sql, rule.getId(), ruleGroup.getId(), alias, user);
						if (!conditionSql.trim().equals("")) {
							if (firstGroupCondition) {
								if (conditionSize == 1 && size == 0) {
									sql = sql + " " + conditionSql;
								} else {
									sql = sql + " (";
									sql = sql + conditionSql;
									sql = sql + ") ";
								}
								firstGroupCondition = false;
							} else {
								if (conditionSize == 1 && size == 0) {
									sql = sql + " " + ruleGroup.getOperate() + conditionSql;
								} else {
									sql = sql + " " + ruleGroup.getOperate() + " (";
									sql = sql + conditionSql;
									sql = sql + ") ";
								}
							}

						}
					}
					// if(ruleGroupList!=null&&!ruleGroupList.isEmpty())
					/*
					 * if(ruleList.size()>1) sql=sql+" )"; if(firstRule)
					 */
					sql = sql + " )";
					firstRule = false;
				}
			}
 		//没有配置角色规则时，默认不显示
 		if(sql.trim().equals(""))
 			sql=" and 1=-1";
 		else
 			sql=" and (1=1 "+sql+" ) ";
 		return sql;
 	}
 	/**
 	 * 
 	* <p>方法名: genGroupSql<／p>
 	* <p>描述: <／p>
 	* @param sql
 	* @param ruleId
 	* @param pgroupid
 	* @param alias
 	* @return
 	 */
 	public String genGroupSql(String sql,String ruleId,String pgroupid,String alias,TSUser user){	
 		Map para=new HashMap();
 		para.put("ruleId", ruleId);
 		para.put("groupId", pgroupid);
 		String groupHql="select * from T_S_DATARULE_GROUP dg";
			groupHql=groupHql+" where dg.status='1' and dg.rule_Id=#{ruleId} and dg.P_GROUPID=#{groupId} and exists (select 1 from T_S_DATACONDITION con where con.status='1' and con.group_Id=dg.id)";
	 		List<TSDataruleGroup> ruleGroupList=commonService.findByQueryString(groupHql, TSDataruleGroup.class, para);
	 		if(ruleGroupList!=null&&!ruleGroupList.isEmpty())
	 		for(TSDataruleGroup ruleGroup:ruleGroupList){
	 			Map paraCondition=new HashMap();
	 			paraCondition.put("ruleId", ruleId);
	 			paraCondition.put("groupId", ruleGroup.getId());
	 			String conditionSql="";
	 			conditionSql=genConditionSql(ruleGroup.getId(),alias,user);
	 			String conditionHql="select count(*)  from T_S_DATACONDITION ";
				conditionHql=conditionHql+" where status='1' and GROUP_ID=#{groupId}";
	 			Long conditionSize=commonService.getCountForJdbc(conditionHql,paraCondition);
	 			String subGroupHql="select count(*) from T_S_DATARULE_GROUP ";
	 			subGroupHql=subGroupHql+" where status='1' and rule_Id=#{ruleId} and P_GROUPID=#{groupId}";
	 			Long size=commonService.getCountForJdbc(subGroupHql,paraCondition);
	 			if(size>0)
	 				conditionSql=conditionSql+genGroupSql(sql,ruleId,ruleGroup.getId(),alias,user);
	 			if(!conditionSql.trim().equals("")){
	 				if(conditionSize==1&&size==0){
	 					sql=sql+" "+ruleGroup.getOperate()+conditionSql;
	 				}else{
	 					sql=sql+" "+ruleGroup.getOperate()+" (";
			 			sql=sql+conditionSql;
			 			sql=sql+") ";
	 				}
	 				
	 			}
	 			
	 		}
	 		
	 		return sql;
 	}
 	/**
 	 * 
 	* <p>方法名: genConditionSql<／p>
 	* <p>描述:根据配置的条件生成sql <／p>
 	* @param groupId 条件分组id
 	* @param alias 表别名
 	* @return
 	 */
 	public String genConditionSql(String groupId,String alias,TSUser user){
 		Map para=new HashMap();
 		para.put("groupId", groupId);
 		String sql="";
 		String conditionHql="select * from T_S_DATACONDITION ";
			conditionHql=conditionHql+" where status='1' and GROUP_ID=#{groupId} order by CON_ORDER";
	 		List<TSDatacondition> conditionList=commonService.findByQueryString(conditionHql, TSDatacondition.class, para);
	 		if(conditionList!=null&&!conditionList.isEmpty())
			for(TSDatacondition condition:conditionList){
				if(!sql.equals(""))
				sql=sql+" "+condition.getOperate()+" ";
				//sql=sql+" ( ";
				if(condition.getFieldType().equals("alldept")){//所有部门
					sql=sql+"  1=1 ";
				}else if(condition.getFieldType().equals("busdept")){//登录人大部(第一级)
					String busdeptId="";
					TSDepart deptBean=commonService.get(TSDepart.class,  user.getDepartId());
					//TSDepart deptBean=user.getTSDepart();
					if(deptBean.getLevelNo()==null||deptBean.getLevelNo().equals(""))
						busdeptId=deptBean.getId();
					else if(deptBean.getLevelNo()!=null&&deptBean.getLevelNo().length()==3)
						busdeptId=deptBean.getId();
					else{
						int deptLevel=condition.getDeptLevel()<1?1*3:condition.getDeptLevel()*3;
						String levelNo=deptBean.getLevelNo().substring(0, deptLevel);
						List<TSDepart> list=commonService.findByProperty(TSDepart.class, "levelNo", levelNo);
						TSDepart pdept=null;
						if(list==null||list.isEmpty())
							pdept=deptBean;
						else
							pdept=list.get(0);
						busdeptId=pdept.getId();
					}
					
					if(!busdeptId.trim().equals("")){
						TSDepart dept=commonService.get(TSDepart.class, busdeptId);
						sql=sql+" exists (select t.ID from T_S_DEPART t where "+alias+"."+condition.getFieldName()+"=t.ID and "+"t.LEVEL_NO like '"+dept.getLevelNo()+"%'  and t.STATUS='1')";
					}else{
						if(deptBean!=null)
						sql=sql+" "+alias+"."+condition.getFieldName()+"='"+deptBean.getId()+"' ";
					}
					
				}else if(condition.getFieldType().equals("subdept")){//登录人部门
					sql=sql+" "+alias+"."+condition.getFieldName()+"='"+user.getDepartId()+"' ";
				}else if(condition.getFieldType().equals("dept")){//指定部门
					sql=sql+" "+alias+"."+condition.getFieldName()+" in ";
					sql=sql+" ('"+condition.getDeptVal().replaceAll(",", "','")+"')";
				}else if(condition.getFieldType().equals("cascadedept")){//指定的部门及下级部门（级联）
					//sql=sql+" "+alias+"."+condition.getFieldName()+" in ";
					//select * from T_S_DEPART t START WITH t.ID in ('30','11','25') CONNECT BY PRIOR t.ID =t.PARENTDEPARTID
					//sql=sql+" (select t.ID from T_S_DEPART t START WITH t.ID in ('"+condition.getDeptVal().replaceAll(",", "','")+"') CONNECT BY PRIOR t.ID =t.PARENTDEPARTID and t.STATUS='1')";
					String deptArr[]=condition.getDeptVal().split(",");
					String authSql="";
					if(deptArr!=null&&deptArr.length>0){
						for(String deptId:deptArr){
							TSDepart dept=commonService.get(TSDepart.class, deptId);
							authSql=authSql+"or t.LEVEL_NO like '"+dept.getLevelNo()+"%'";
						}
					}
					if(authSql.startsWith("or")){
						authSql=authSql.substring(2);
						authSql="and ("+authSql+")";
					}
						
					if(!authSql.equals(""))
						sql=sql+" (select t.ID from T_S_DEPART t where 1=1 and "+alias+"."+condition.getFieldName()+"=t.ID and "+authSql+"  and t.STATUS='1')";
				}else if(condition.getFieldType().equals("varDeptCasca")){
					int deptLevel=condition.getDeptLevel()<1?10*3:condition.getDeptLevel()*3;
					String opType=convertOpType(condition.getConOperate(),condition.getFieldValue());
					String authSql=" t.LEVEL_NO like (select substr(d12.LEVEL_NO,1,"+deptLevel+") from T_S_DEPART d12 where d12.ID=#{"+condition.getFieldValue()+"})||'%'";
					sql=sql+" exists (select t.ID from T_S_DEPART t where 1=1 and "+alias+"."+condition.getFieldName()+"=t.ID and "+authSql+"  and t.STATUS='1') ";
				}else if(condition.getFieldType().equals("varPartDeptCasca")){
					int deptLevel=condition.getDeptLevel()<1?10*3:condition.getDeptLevel()*3;
					String opType=convertOpType(condition.getConOperate(),condition.getFieldValue());
					String authSql="";
					//authSql=" ( t.LEVEL_NO like (select substr(d12.LEVEL_NO,0,"+deptLevel+") from T_S_DEPART d12 where d12.ID='"+user.getDepartId()+"')||'%'";
					String levelNo=authSql=this.getAuthDeptLevelNo(deptLevel,user.getDepartId());
					List<String> levelNoList=new ArrayList<String>();
					levelNoList.add(levelNo);
					authSql=" ( t.LEVEL_NO like '"+levelNo+"%'";
					String partDepts=user.getPartDept()==null?"":user.getPartDept();
					if(!partDepts.equals("")){
						String [] deptArr=partDepts.split(",");
						for(String dept:deptArr){
							levelNo=getAuthDeptLevelNo(deptLevel,dept);
							if(!levelNoList.contains(levelNo))
								authSql=authSql+" or  "+"t.LEVEL_NO like '"+levelNo+"%'";
						}
					}
					authSql=authSql+" ) ";
					sql=sql+" exists (select t.ID from T_S_DEPART t where 1=1 and "+alias+"."+condition.getFieldName()+"=t.ID and "+authSql+"  and t.STATUS='1') ";
				}/*else if(condition.getFieldType().equals("uservar")){
					sql=sql+" "+alias+"."+condition.getFieldName()+"='"+user.getUserName()+"' ";
				}*/else{
					sql=sql+alias+"."+condition.getFieldName();
					String value="";
					if(condition.getFieldType().equals("uservar")){
						//sql=sql+" "+alias+"."+condition.getFieldName()+"='"+user.getUserName()+"' ";
						value="'"+user.getUserName()+"' ";
					} else if(condition.getFieldType().equals("number")||condition.getFieldType().equals("boolean"))
						value=condition.getFieldValue();
					/*else if(condition.getConoperate().indexOf("like")>-1)
						value="'"+condition.getFieldValue()+"' ";*/
					else if(condition.getFieldType().equals("string"))
						value="'"+condition.getFieldValue()+"' ";
					
					sql=sql+convertOpType(condition.getConOperate(),value);
					/*if(condition.getConOperate().equals("equal")){
						sql=sql+"="+value+" ";
					}else if(condition.getConOperate().equals("lt")){
						sql=sql+"<"+value+" ";
					}else if(condition.getConOperate().equals("gt")){
						sql=sql+">"+value+" ";
					}else if(condition.getConOperate().equals("lt=")){
						sql=sql+"<="+value+" ";
					}else if(condition.getConOperate().equals("gt=")){
						sql=sql+">="+value+" ";
					}else if(condition.getConOperate().equals("include")){
						sql=sql+"in ("+value+") ";
					}else if(condition.getConOperate().equals("noinclude")){
						sql=sql+"not in ("+value+") ";
					}else if(condition.getConOperate().equals("like")){
						sql=sql+"like '%"+condition.getFieldValue()+"%' ";
					}else if(condition.getConOperate().equals("likestart")){
						sql=sql+"like '"+condition.getFieldValue()+"%' ";
					}else if(condition.getConOperate().equals("likeend")){
						sql=sql+"like '%"+condition.getFieldValue()+"' ";
					}else if(condition.getConOperate().equals("noequal")){
						sql=sql+"<>"+value+" ";	
					}*/
				}
				//sql=sql+") ";
			}
			
			return sql;
 	}
	public String getAuthDeptLevelNo(int deptLevel,String departId){
		String authSql="";
		authSql="select substr(d12.LEVEL_NO,1,"+deptLevel+") levelno from T_S_DEPART d12 where d12.ID='"+departId+"'";
		Map ret=commonService.findOneForJdbc(authSql, new HashMap());
		if(ret!=null)
			return ret.get("levelno")==null?"":ret.get("levelno").toString();
		return "";
	}
 	public String convertOpType(String opType,String value){
 		String sql="";
			if(opType.equals("equal")){
				sql=sql+"="+value+" ";
			}else if(opType.equals("lt")){
				sql=sql+"<"+value+" ";
			}else if(opType.equals("gt")){
				sql=sql+">"+value+" ";
			}else if(opType.equals("lt=")){
				sql=sql+"<="+value+" ";
			}else if(opType.equals("gt=")){
				sql=sql+">="+value+" ";
			}else if(opType.equals("include")){
				sql=sql+"in ("+value+") ";
			}else if(opType.equals("noinclude")){
				sql=sql+"not in ("+value+") ";
			}else if(opType.equals("like")){
				sql=sql+"like '%"+value+"%' ";
			}else if(opType.equals("likestart")){
				sql=sql+"like '"+value+"%' ";
			}else if(opType.equals("likeend")){
				sql=sql+"like '%"+value+"' ";
			}else if(opType.equals("noequal")){
				sql=sql+"<>"+value+" ";	
			}
			return sql;
 	}
 	public AjaxJson getRoleRuleList(Map reqMap,String page,String rows){
 		AjaxJson j=new AjaxJson();
 		String sql="from T_S_DATARULE dr left join T_S_ROLE_DATARULE rd on   rd.RULE_CODE=dr.RULE_CODE and rd.ROLE_CODE='"+reqMap.get("roleCode")+"' where dr.STATUS='1' ";
 		String select="select rd.ID,dr.RULE_NAME, dr.RULE_CODE,dr.MODULE_NAME ";
 		
 		if(reqMap.containsKey("hasRule")&&reqMap.get("hasRule").equals("1"))
 		sql=sql+" and rd.RULE_CODE is not null";
 		if(reqMap.containsKey("hasRule")&&reqMap.get("hasRule").equals("0"))
 	 		sql=sql+" and rd.RULE_CODE is  null";
 		String orderby=" order by dr.MODULE_NAME ";
		List beanList =commonService.findForJdbcPage(select+sql+orderby, Map.class, reqMap, Integer.parseInt(page), Integer.parseInt(rows));
		String countSql="select count(1) "+sql;
		Long total=commonService.getCountForJdbc(countSql, reqMap);
		j.setTotal(total);
		j.setObj(beanList);
		return j;
 	}
 	public List<TSRoleDatarule> getRoleRuleList(Map reqMap){
 		AjaxJson j=new AjaxJson();
 		String sql="select * from T_S_ROLE_DATARULE rd where rd.ROLE_CODE=#{roleCode}  ";
 		sql=sql+" and rd.RULE_CODE=#{ruleCode}";
		List<TSRoleDatarule> beanList =commonService.findByQueryString(sql, TSRoleDatarule.class, reqMap);
		return beanList;
 	}
}